﻿using System.Diagnostics;
using System.Reflection;
using System.Windows;
using KinonekoSoftware.Studio;
using KinonekoSoftware.Studio.Bus;
using Verbose = KinonekoSoftware.Studio.Messages.Verbose;

// ReSharper disable UnusedMember.Local
namespace KinonekoSoftware.Studio.ViewModels
{

    public abstract class TabViewModelCore : TabViewModel, IMessageBus<MessageCore>
    {
        private readonly MessageBus<MessageCore>               _bus;
        private readonly Dictionary<Type, Action<MessageCore>> _messageHandlers;

        protected TabViewModelCore()
        {
            _messageHandlers = new Dictionary<Type, Action<MessageCore>>();
            _bus             = new MessageBus<MessageCore>(OnMessagePumping);
            EnableSafetyExit = true;
            SnapshotCommand  = CreateCommand(DoSnapshotCommand);
            InitializeHandlers();
        }
        
        private void DoSnapshotCommand()
        {
            PushToView(new SnapshotMessage());
        }


        public void Snapshot(Action<object> snapshotCallback)
        {
            OnSnapshot(new SnapshotMessage { Callback = snapshotCallback });
        }

        protected virtual void OnSnapshot(SnapshotMessage message)
        {
            PushToView(message);
        }
        
        public void Interest<TMSG>(MessageHandler<MessageCore> handler) where TMSG : IMessage
        {
            _bus.Interest<TMSG>(handler);
        }

        #region CommandMessage Handlers

        [MessageHandler(typeof(CommandMessage))]
        private void Handle_CommandMSG(MessageCore msg)
        {
            var commandMSG = (CommandMessage)msg;

            OnCommandProc(commandMSG.Verbose);
        }

        protected virtual void OnCommandProc(Verbose verbose)
        {
        }

        #endregion

        #region MessageQueues

        protected virtual void FromViewModel_MsgProc(MessageCore message)
        {
            if (message is not null && _messageHandlers.TryGetValue(message.GetType(), out var handler))
            {
                handler(message);
            }
        }

        public void InitializeHandlers()
        {
            //
            // 当前方法为在当前类中寻找消息处理器（并不会搜索基类）
            var handlers = GetType()
                          .GetMethods(BindingFlags.Instance | BindingFlags.NonPublic)
                          .Where(x => x.IsDefined(typeof(MessageHandlerAttribute), true))
                          .Select(x => new ValueTuple<MessageHandlerAttribute, Action<MessageCore>>(
                                                                                                    x.GetCustomAttribute<MessageHandlerAttribute>(),
                                                                                                    x.CreateDelegate<Action<MessageCore>>(this)))
                          .Select(x => new KeyValuePair<Type, Action<MessageCore>>(x.Item1.MessageType, x.Item2));

            _messageHandlers.AddMany(handlers);
            _messageHandlers.TryAdd(typeof(CommandMessage), Handle_CommandMSG);
            Trace.WriteLine($"【初始化】加载了{_messageHandlers.Count}个消息处理器");
        }

        private void OnMessagePumping(MessageCore message) => FromViewModel_MsgProc(message);



        protected void SetQueue(TabViewModelSub item) => item?.SetQueue(_bus);


        void IMessageBus<MessageCore>.OnNext(MessageCore message)
        {
            _bus.OnNext(message);
        }

        #endregion

        protected IMessageBus<MessageCore> MQ              => _bus;
        public    ICommandEX               SnapshotCommand { get; }
    }
}